package monitor

import (
	"context"
	"encoding/json"
	"fmt"
	gorillaWs "github.com/gorilla/websocket"
	"github.com/kataras/iris/v12/websocket"
	"github.com/kataras/neffos"
	"github.com/kataras/neffos/gorilla"
	"gluenet/pkg/apis"
	"gluenet/pkg/meta"
	"gluenet/pkg/ops"
	"math/rand"
	"net/http"
	"time"
)

func Memory(c *apis.GlueContext) {
	startTime, _ := c.WebContext.URLParamInt64("start")
	endTime, _ := c.WebContext.URLParamInt64("end")
	lookBack, _ := c.WebContext.URLParamInt64("lookback")
	guid := c.WebContext.URLParam("guid")
	child := c.WebContext.URLParam("child")
	kind := c.WebContext.URLParam("object")

	if lookBack != 0 {
		endTime = time.Now().Unix()
		startTime = endTime - lookBack + 1
	}
	size := endTime - startTime + 1
	if size <= 0 {
		c.Logger.Errorf("error : size less < than")
		c.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("error : size less < than"), nil))
		return
	}

	var data *meta.Metrics
	if err := c.DataBase.MetricsQuerySpecial(ops.Memused, kind, guid, child, startTime, endTime, &data); err != nil {
		c.Logger.Errorf("query container memory error: %v", err)
		c.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("query container memory error %v", err), nil))
		return
	}

	c.WebContext.JSON(apis.ResponseOK(data.Metrics))
}

func GetMemorySocket(c *apis.GlueContext) {
	guid := c.WebContext.URLParam("guid")
	child := c.WebContext.URLParam("child")
	kind := c.WebContext.URLParam("object")

	ctx, cancel := context.WithCancel(c.Context)
	var ActuallyNodeCpu = websocket.New(gorilla.Upgrader(gorillaWs.Upgrader{
		CheckOrigin: func(*http.Request) bool { return true },
	}), websocket.Events{
		websocket.OnNativeMessage: func(conn *neffos.NSConn, message neffos.Message) error { return nil },
	})

	ActuallyNodeCpu.OnConnect = func(n *websocket.Conn) error {
		c.Logger.Debugf("OnConnect from server %v", n.ID())
		tk := time.NewTicker(time.Second * 6)
		for {
			select {
			case <-tk.C:
				end := time.Now().Unix()
				start := end - 11
				//data := simulateMem(start, end)

				var data *meta.Metrics
				if err := c.DataBase.MetricsQuerySpecial(ops.Memusedlast, kind, guid, child, start, end, &data); err != nil {
					c.Logger.Errorf("query container memory error: %v", err)
					c.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("query container memory error %v", err), nil))
					continue
				}

				bts, _ := json.Marshal(data)
				n.Write(neffos.Message{
					Body:     bts,
					IsNative: true,
				})
			case <-ctx.Done():
				c.Logger.Debugf("push down %v", n.ID())
				return nil
			}
		}
		return nil
	}

	ActuallyNodeCpu.OnDisconnect = func(n *websocket.Conn) {
		cancel()
		c.Logger.Debugf("Disconnected from server", n.ID())
	}

	ActuallyNodeCpu.OnUpgradeError = func(err error) {
		cancel()
		c.Logger.Debugf("OnUpgradeError from server %v", err)
	}

	websocket.Handler(ActuallyNodeCpu)(c.WebContext)
}

func simulateMem(start, end int64) []map[string]interface{} {
	size := end - start + 1
	data := make([]map[string]interface{}, size)
	for i := int64(0); i < size; i++ {
		t := time.Unix(i+start, 0)
		v := float64(t.Second())/10 + 10 + rand.Float64()*10
		data[i] = map[string]interface{}{
			"label": "memory_usage",
			"time":  t.Format(time.RFC3339Nano),
			"value": v,
			"limit": 100,
		}
	}
	return data
}
